#include "database/mysql_pool.h"
#include "common/logger/logger.h"
#include <chrono>

namespace database {

// MySQLConnection 实现
MySQLConnection::MySQLConnection() : mysql_(nullptr) {
    mysql_ = mysql_init(nullptr);
    if (!mysql_) {
        LOG_ERROR("MySQL初始化失败");
    }
}

MySQLConnection::~MySQLConnection() {
    close();
}

bool MySQLConnection::connect(const std::string& host, const std::string& user, const std::string& passwd,
                             const std::string& db, unsigned int port) {
    if (!mysql_) {
        return false;
    }
    
    // 设置连接超时时间
    int timeout = 5;
    mysql_options(mysql_, MYSQL_OPT_CONNECT_TIMEOUT, &timeout);
    
    // 设置自动重连
    bool reconnect = 1;
    mysql_options(mysql_, MYSQL_OPT_RECONNECT, &reconnect);
    
    // 使用UTF8字符集
    mysql_options(mysql_, MYSQL_SET_CHARSET_NAME, "utf8mb4");
    
    // 连接数据库
    if (!mysql_real_connect(mysql_, host.c_str(), user.c_str(), passwd.c_str(),
                          db.c_str(), port, nullptr, 0)) {
        LOG_ERROR("MySQL连接失败: " + getError());
        return false;
    }
    
    LOG_DEBUG("MySQL连接成功");
    return true;
}

bool MySQLConnection::query(const std::string& sql) {
    if (!mysql_) {
        LOG_ERROR("MySQL未初始化");
        return false;
    }
    
    int ret = mysql_query(mysql_, sql.c_str());
    if (ret != 0) {
        LOG_ERROR("MySQL查询失败: " + getError() + ", SQL: " + sql);
        return false;
    }
    return true;
}

MYSQL_RES* MySQLConnection::getResult() {
    if (!mysql_) {
        LOG_ERROR("MySQL未初始化");
        return nullptr;
    }
    
    return mysql_store_result(mysql_);
}

uint64_t MySQLConnection::getInsertId() {
    if (!mysql_) {
        LOG_ERROR("MySQL未初始化");
        return 0;
    }
    
    return mysql_insert_id(mysql_);
}

uint64_t MySQLConnection::getAffectedRows() {
    if (!mysql_) {
        LOG_ERROR("MySQL未初始化");
        return 0;
    }
    
    return mysql_affected_rows(mysql_);
}

bool MySQLConnection::startTransaction() {
    return query("START TRANSACTION");
}

bool MySQLConnection::commit() {
    return query("COMMIT");
}

bool MySQLConnection::rollback() {
    return query("ROLLBACK");
}

std::string MySQLConnection::getError() {
    if (!mysql_) {
        return "MySQL未初始化";
    }
    
    return mysql_error(mysql_);
}

void MySQLConnection::close() {
    if (mysql_) {
        mysql_close(mysql_);
        mysql_ = nullptr;
    }
}

bool MySQLConnection::ping() {
    if (!mysql_) {
        return false;
    }
    
    return mysql_ping(mysql_) == 0;
}

// MySQLPool 实现
std::shared_ptr<MySQLPool> MySQLPool::create(const std::string& host, const std::string& user,
                                           const std::string& passwd, const std::string& db,
                                           unsigned int port, size_t poolSize) {
    return std::shared_ptr<MySQLPool>(new MySQLPool(host, user, passwd, db, port, poolSize));
}

MySQLPool::MySQLPool(const std::string& host, const std::string& user, const std::string& passwd,
                   const std::string& db, unsigned int port, size_t poolSize)
    : host_(host), user_(user), passwd_(passwd), db_(db), 
      port_(port), poolSize_(poolSize), isRunning_(true), createdCount_(0) {
    
    // 初始化连接池
    for (size_t i = 0; i < poolSize; i++) {
        auto conn = createConnection();
        if (conn) {
            connQueue_.push(conn);
            createdCount_++;
        }
    }
    
    LOG_INFO("MySQL连接池初始化完成，池大小: " + std::to_string(poolSize));
}

MySQLPool::~MySQLPool() {
    close();
}

std::shared_ptr<MySQLConnection> MySQLPool::createConnection() {
    auto conn = std::make_shared<MySQLConnection>();
    if (!conn->connect(host_, user_, passwd_, db_, port_)) {
        LOG_ERROR("创建MySQL连接失败");
        return nullptr;
    }
    return conn;
}

std::shared_ptr<MySQLConnection> MySQLPool::getConnection(int timeoutMs) {
    std::unique_lock<std::mutex> lock(mutex_);
    
    if (!isRunning_) {
        LOG_ERROR("连接池已关闭");
        return nullptr;
    }
    
    // 等待可用连接
    if (connQueue_.empty()) {
        if (createdCount_ < poolSize_) {
            // 还可以创建新连接
            lock.unlock();
            auto conn = createConnection();
            if (conn) {
                createdCount_++;
                return conn;
            }
        }
        
        // 等待已有连接归还
        if (timeoutMs > 0) {
            auto timeout = std::chrono::milliseconds(timeoutMs);
            if (!condition_.wait_for(lock, timeout, [this] { return !connQueue_.empty() || !isRunning_; })) {
                LOG_ERROR("获取MySQL连接超时");
                return nullptr;
            }
        } else {
            condition_.wait(lock, [this] { return !connQueue_.empty() || !isRunning_; });
        }
        
        if (!isRunning_) {
            LOG_ERROR("连接池已关闭");
            return nullptr;
        }
        
        if (connQueue_.empty()) {
            LOG_ERROR("没有可用的MySQL连接");
            return nullptr;
        }
    }
    
    // 获取一个连接
    auto conn = connQueue_.front();
    connQueue_.pop();
    
    lock.unlock();
    
    // 检查连接是否有效
    if (!conn->ping()) {
        LOG_WARNING("MySQL连接已断开，重新连接");
        if (!conn->connect(host_, user_, passwd_, db_, port_)) {
            LOG_ERROR("重新连接MySQL失败");
            lock.lock();
            createdCount_--;
            lock.unlock();
            return nullptr;
        }
    }
    
    return conn;
}

void MySQLPool::releaseConnection(std::shared_ptr<MySQLConnection> conn) {
    if (!conn) {
        return;
    }
    
    std::lock_guard<std::mutex> lock(mutex_);
    if (isRunning_) {
        connQueue_.push(conn);
        condition_.notify_one();
    }
}

void MySQLPool::close() {
    std::lock_guard<std::mutex> lock(mutex_);
    isRunning_ = false;
    
    // 清空连接队列
    while (!connQueue_.empty()) {
        auto conn = connQueue_.front();
        connQueue_.pop();
        conn->close();
    }
    
    createdCount_ = 0;
    condition_.notify_all();
    
    LOG_INFO("MySQL连接池已关闭");
}

size_t MySQLPool::getAvailableCount() {
    std::lock_guard<std::mutex> lock(mutex_);
    return connQueue_.size();
}

size_t MySQLPool::getUsedCount() {
    std::lock_guard<std::mutex> lock(mutex_);
    return createdCount_ - connQueue_.size();
}

} // namespace database 